﻿using Abp.AspNetCore.Mvc.Auditing;
using Castle.Core.Logging;
using Microsoft.AspNetCore.Http;
using Microsoft.Net.Http.Headers;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;

namespace Mt.Site.Core
{
    public class MtClientInfoProvider : HttpContextClientInfoProvider
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public MtClientInfoProvider(IHttpContextAccessor httpContextAccessor)
            :base(httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;

            Logger = NullLogger.Instance;
        }



        protected override string GetClientIpAddress()
        {
            var httpContext = _httpContextAccessor.HttpContext;
            if (httpContext == null)
            {
                return null;
            }

            List<string> keyList = new List<string>{
                "HTTP_X_REAL_IP",
                "HTTP_X_FORWARDED_FOR",
                "X-Client-IP",
                "X-Real-IP",
                "X-Real-Ip",
                "WL-Proxy-Client-IP",
                "PROXY_CLIENT_IP",
                "X_Forwarded_For" 
            };

            string clientIp = null;
            for (int i = 0; i < keyList.Count; i++)
            {
                clientIp = httpContext.Request.Headers[keyList[i]].ToString();
                if (!string.IsNullOrEmpty(clientIp))
                {
                    break;
                }
            }

            //nginx代理一般会加上此请求头。
            //var clientIp = httpContext.Request.Headers["HTTP_X_REAL_IP"].ToString();
            //if (string.IsNullOrEmpty(clientIp))
            //{
            //    //Squid 开发的字段，只有在通过了HTTP代理或者负载均衡服务器时才会添加该项
            //    //格式为 X-Forwarded-For:client1,proxy1,proxy2，一般情况下，第一个ip为客户端真实ip，后面的为经过的代理服务器ip。
            //    clientIp = httpContext.GetServerVariable("HTTP_X_FORWARDED_FOR");
            //}

            if (string.IsNullOrEmpty(clientIp))
            {
                clientIp = httpContext?.Connection?.RemoteIpAddress?.ToString();
            }

            if(clientIp == null)
            {
                return null;
            }

            try
            {
                foreach (var hostAddress in Dns.GetHostAddresses(clientIp))
                {
                    if (hostAddress.AddressFamily == AddressFamily.InterNetwork || hostAddress.AddressFamily == AddressFamily.InterNetworkV6)
                    {
                        return hostAddress.ToString();
                    }
                }

                var hostName = Dns.GetHostName();
                foreach (var hostAddress in Dns.GetHostAddresses(hostName))
                {
                    if (hostAddress.AddressFamily == AddressFamily.InterNetwork || hostAddress.AddressFamily == AddressFamily.InterNetworkV6)
                    {
                        return hostAddress.ToString();
                    }
                }
            }
            catch //(Exception ex)
            {
                //Logger.Debug(ex.ToString());
            }

            return clientIp;
        }
    }
}